

#include <stdlib.h>
#include "arraylist.h"

#ifndef NULL
#define NULL (void*)0
#endif

#define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#if 0
#define offsetof(TYPE,MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
#define container_of(ptr,type,member) ( {\
	const typeof(((type*)0)->member) *__mptr = (ptr); \
	(type*)((char*)__mptr - offsetof(type, member)); })
#endif

#define prefetch(x) __builtin_prefetch(x)

#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
	pos = pos->next)

#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
	pos = n, n = pos->next)


static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) {
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}


static inline void list_add(struct list_head *new, struct list_head *head){
	__list_add(new, head, head->next);
}

static inline void __list_del(struct list_head * prev, struct list_head * next)

{
	next->prev = prev;
	prev->next = next;
}

static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);

	entry->next = entry;
	entry->prev = entry;
}


static inline int list_empty(const struct list_head *head)
{
	return head->next == head;
}


parraylist_t arraylist_new() {
	return (parraylist_t)malloc(sizeof(arraylist_t));
}

int arraylist_free(parraylist_t list) {
	struct list_head *pos;
	struct list_head *n;

	list_for_each_safe(pos, n, &list->head) {
		parraylist_t list_item = list_entry(pos, arraylist_t, head);

		list_del(pos);
		free(list_item);
	}

	return 0;
}

int arraylist_add(parraylist_t list, void *item) {
	parraylist_t list_item = (parraylist_t)malloc(sizeof(arraylist_t));
	if (list_item == NULL) {
		return -1;
	}

	list_item->ptr = item;

	list_add(&list_item->head, &list->head);

	return 0;
}

int arraylist_delbyindex(parraylist_t list, int index) {
	struct list_head *pos;
	struct list_head *n;
	int i = 0;

	list_for_each_safe(pos, n, &list->head) {
		if (i == index) {
			parraylist_t list_item = list_entry(pos, arraylist_t, head);

			list_del(pos);
			free(list_item);

			return 0;
		}
		i++;
	}

	return -1;
}

int arraylist_delbyitem(parraylist_t list, void *item) {
	struct list_head *pos;
	struct list_head *n;

	list_for_each_safe(pos, n, &list->head) {
		parraylist_t list_item = list_entry(pos, arraylist_t, head);
		if (list_item->ptr == item) {
			list_del(pos);
			free(list_item);

			return 0;
		}
	}

	return -1;
}

int arraylist_count(parraylist_t list) {
	struct list_head *pos;
	struct list_head *n;
	int i = 0;

	list_for_each_safe(pos, n, &list->head) {
		i++;
	}

	return i;
}